﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;

using System;
using WebDemo.Data;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
using WebDemo.Models;

namespace WebDemo.Controllers
{
    public class AccountController : Controller
    {
        private readonly MySQLDbContext _context;
        private readonly ILogger<AccountController> _logger;

        public AccountController(MySQLDbContext context, ILogger<AccountController> logger)
        {
            _context = context;
            _logger = logger;
        }

        [HttpGet]
        public IActionResult Login(string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Login(string username, string password, string returnUrl = null)
        {
            var user = await _context.Users.FirstOrDefaultAsync(u => u.Username == username);

            if (user != null && VerifyPasswordHash(password, user.PasswordHash))
            {
                await HttpContext.SignInAsync("CookieAuthentication", new ClaimsPrincipal(new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Name,username),
                new Claim(ClaimTypes.NameIdentifier,user.Id.ToString())

            }, "CookieAuthentication")));

                user.LastLogin = DateTime.UtcNow;
                await _context.SaveChangesAsync();

                _logger.LogInformation("User {Username} logged in", username);

                return RedirectToLocal(returnUrl);
            }

            //ModelState.AddModelError("", "Invalid username or password.");
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Logout()
        {
            await HttpContext.SignOutAsync("CookieAuthentication");
            _logger.LogInformation("User logged out");
            return RedirectToAction(nameof(Login));
        }

        private static bool VerifyPasswordHash(string password, string storedHash)
        {
            // 实际项目中应使用更安全的哈希算法如BCrypt
            return BCrypt.Net.BCrypt.Verify(password, storedHash);
        }

        private IActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction(nameof(HomeController.Index), "Home");
            }
        }

        //注册用户名和密码
        [HttpGet]
        public IActionResult Register()
        {
            return View();
        }


        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Register(string username, string password)
        {
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
            {
                ModelState.AddModelError("", "Username and password are required.");
                return View();
            }

            if (await _context.Users.AnyAsync(u => u.Username == username))
            {
                ModelState.AddModelError("", "Username already exists.");
                return View();
            }

            var newUser = new User
            {
                Username = username,
                PasswordHash = HashPassword(password),
                LastLogin = DateTime.UtcNow
            };

            await _context.Users.AddAsync(newUser);
            await _context.SaveChangesAsync();

            await HttpContext.SignInAsync("CookieAuthentication", new ClaimsPrincipal(new ClaimsIdentity(new[]
            {
            new Claim(ClaimTypes.Name, newUser.Username),
            new Claim(ClaimTypes.NameIdentifier, newUser.Id.ToString())
        }, "CookieAuthentication")));

            _logger.LogInformation("User {Username} registered and logged in", username);

            return RedirectToAction(nameof(HomeController.Index), "Home");
        }
        private static string HashPassword(string password)
        {
            // 使用 BCrypt 进行密码哈希
            return BCrypt.Net.BCrypt.HashPassword(password, BCrypt.Net.BCrypt.GenerateSalt());
        }

    }
}
